package org.eclipse.emf.extensions;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.db.Activator;
import org.eclipse.emf.ecore.EPackage;

public abstract class DBAdapterFactoryImpl implements IDBAdapterFactory {
    private static final Properties NO_PROPERTIES=new Properties();

    private final String subProtocol;
    private final String driverName;
    private Driver driver;

    public DBAdapterFactoryImpl(String subProtocol, String driverName) {
        this.driverName=driverName;
        Assert.isNotNull(subProtocol, "Subprotocol * must * not be null"); //$NON-NLS-1$
        Assert.isNotNull(driverName, "Driver * must * not be null"); //$NON-NLS-1$
        this.subProtocol=subProtocol;
    }

    @Override
    public IDBSchema getSchema(String url, EPackage pkg, ConnectionWrapper wrapFunction) throws SQLException {
        if (url.startsWith("jdbc:" + subProtocol)) { //$NON-NLS-1$
            try {
                if (driver == null)
                    driver=((Class<Driver>) Class.forName(driverName, true, getClass().getClassLoader())).newInstance();

                Connection connection=driver.connect(url, NO_PROPERTIES); //DriverManager.getConnection(url);
                if (wrapFunction != null)
                    connection=wrapFunction.wrap(connection);
                connection.setTransactionIsolation(getTransactionIsolation());
                return createSchema(connection, pkg);
            } catch (Exception e) {
                Activator.log(IStatus.ERROR, "Failed initializing driver", e); //$NON-NLS-1$
            }
        }
        return null;
    }

    protected int getTransactionIsolation() {
        return Connection.TRANSACTION_READ_COMMITTED;
    }

    protected abstract IDBSchema createSchema(Connection connection, EPackage pkg) throws SQLException;
}
